package com.nidu.demo.excel.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.nidu.demo.dict.cache.DictCacheService;
import com.nidu.demo.excel.listener.ExcelValidationListener;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Validator;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Excel导入工具类
 * 直接使用DictCacheService，无需额外抽象
 *
 * @author nidu
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ExcelImportUtil {

    private final DictCacheService dictCacheService;
    private final Validator validator;

    /**
     * 从MultipartFile读取Excel数据（带验证）
     */
    public <T> ExcelImportResult<T> readWithValidation(MultipartFile file, Class<T> clazz) {
        return readWithValidation(file, clazz, null);
    }

    /**
     * 从MultipartFile读取Excel数据（带验证和数据处理）
     */
    public <T> ExcelImportResult<T> readWithValidation(MultipartFile file, Class<T> clazz,
                                                       ExcelValidationListener.DataProcessor<T> processor) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        try {
            return readWithValidationFromStream(file.getInputStream(), clazz, processor);
        } catch (IOException e) {
            log.error("读取Excel文件失败", e);
            throw new RuntimeException("读取Excel文件失败", e);
        }
    }

    /**
     * 从输入流读取Excel数据（带验证）
     */
    public <T> ExcelImportResult<T> readWithValidationFromStream(InputStream inputStream,
                                                                 Class<T> clazz,
                                                                 ExcelValidationListener.DataProcessor<T> processor) {
        try (InputStream is = inputStream) {
            ExcelValidationListener<T> listener = new ExcelValidationListener<>(
                    validator, dictCacheService, processor);

            EasyExcel.read(is, clazz, listener).sheet().doRead();

            return ExcelImportResult.<T>builder()
                    .successList(listener.getDataList())
                    .errorList(listener.getErrorList())
                    .totalCount(listener.getDataList().size() + listener.getErrorList().size())
                    .successCount(listener.getDataList().size())
                    .errorCount(listener.getErrorList().size())
                    .build();

        } catch (IOException e) {
            log.error("读取Excel文件失败", e);
            throw new RuntimeException("读取Excel文件失败", e);
        }
    }

    /**
     * 简单读取（不带验证，兼容旧版本）
     */
    public <T> List<T> readFromFile(MultipartFile file, Class<T> clazz) {
        ExcelImportResult<T> result = readWithValidation(file, clazz);
        return result.getSuccessList();
    }

    /**
     * 批量读取Excel数据（适用于大文件）
     */
    public <T> void readBatchFromFile(MultipartFile file, Class<T> clazz,
                                      int batchSize, Consumer<List<T>> consumer) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        try (InputStream is = file.getInputStream()) {
            EasyExcel.read(is, clazz, new ReadListener<T>() {
                private List<T> batchList = new ArrayList<>();

                @Override
                public void invoke(T data, AnalysisContext context) {
                    batchList.add(data);
                    if (batchList.size() >= batchSize) {
                        consumer.accept(new ArrayList<>(batchList));
                        batchList.clear();
                    }
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    if (!batchList.isEmpty()) {
                        consumer.accept(batchList);
                    }
                    log.info("Excel批量读取完成");
                }
            }).sheet().doRead();

        } catch (IOException e) {
            log.error("批量读取Excel文件失败", e);
            throw new RuntimeException("批量读取Excel文件失败", e);
        }
    }

    /**
     * Excel导入结果
     */
    @lombok.Data
    @lombok.Builder
    public static class ExcelImportResult<T> {
        private List<T> successList;
        private List<ExcelValidationListener.ExcelValidationError<T>> errorList;
        private int totalCount;
        private int successCount;
        private int errorCount;
    }
}